import type { direction } from '../types'
/**
 * 判断两个4x4棋盘是否完全相等
 * @param a 棋盘a
 * @param b 棋盘b
 */
function boardsEqual(a: number[][], b: number[][]): boolean {
  for (let i = 0; i < a.length; i++) {
    for (let j = 0; j < a[i].length; j++) {
      if (a[i][j] !== b[i][j])
        return false
    }
  }
  return true
}

/**
 * 2048游戏核心逻辑Hook
 */
export function useGame() {
  const board = ref<number[][]>([]) // 4x4棋盘，数字方块，0表示空
  const score = ref(0) // 当前得分

  // 初始化棋盘，清空后随机生成两个数字块
  const initBoard = () => {
    board.value = Array.from({ length: 4 }, () => Array(4).fill(0))
    spawn()
    spawn()
  }

  // 重新开始游戏，分数归零，棋盘初始化
  const restart = () => {
    score.value = 0
    initBoard()
  }

  // 随机生成2或4在空白格子中
  const spawn = () => {
    const emptyCells: [number, number][] = []
    board.value.forEach((row, i) =>
      row.forEach((cell, j) => {
        if (cell === 0)
          emptyCells.push([i, j])
      }),
    )
    if (emptyCells.length > 0) {
      const [i, j] = emptyCells[Math.floor(Math.random() * emptyCells.length)]
      board.value[i][j] = Math.random() < 0.9 ? 2 : 4
    }
  }

  /**
   * 执行移动操作
   * @param direction 方向: 'left' | 'right' | 'up' | 'down'
   * @returns 本次移动获得的分数（只有实际移动或合并才有分）
   */
  const move = (direction: direction): number => {
    let gainedScore = 0
    const oldBoard = board.value.map(row => [...row]) // 深拷贝当前棋盘用于对比

    /**
     * 对单行/单列数组进行合并操作（左移逻辑）
     */
    const operate = (rows: number[][]) =>
      rows.map((row) => {
        const filtered = row.filter(n => n) // 过滤掉0，得到非空块
        for (let i = 0; i < filtered.length - 1; i++) {
          if (filtered[i] === filtered[i + 1]) {
            filtered[i] *= 2 // 合并，数值翻倍
            gainedScore += filtered[i] // 累加分数
            filtered[i + 1] = 0 // 合并后后面格子清零，避免重复合并
          }
        }
        const merged = filtered.filter(n => n) // 再次过滤掉合并产生的0
        return [...merged, ...Array(4 - merged.length).fill(0)] // 补齐右侧空格
      })

    if (direction === 'left') {
      board.value = operate(board.value)
    }
    else if (direction === 'right') {
      // 右移等价于翻转行后做左移，再翻转回去
      board.value = operate(board.value.map(row => row.slice().reverse())).map(row => row.reverse())
    }
    else if (direction === 'up') {
      // 上移操作需要先把列转成行操作
      const cols = board.value[0].map((_, i) => board.value.map(row => row[i]))
      const newCols = operate(cols)
      board.value = newCols[0].map((_, i) => newCols.map(row => row[i]))
    }
    else if (direction === 'down') {
      // 下移类似上移，先翻转列，再左移，再翻转回来
      const cols = board.value[0].map((_, i) => board.value.map(row => row[i]).reverse())
      const newCols = operate(cols).map(row => row.reverse())
      board.value = newCols[0].map((_, i) => newCols.map(row => row[i]))
    }
    else {
      // 非法方向不处理
      return 0
    }

    // 只有当棋盘状态发生变化时才生成新块
    if (!boardsEqual(board.value, oldBoard)) {
      spawn()
      return gainedScore
    }
    return 0
  }

  initBoard()

  return { board, score, move, restart }
}
